﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

using Aspose.Words;
using Aspose.Words.Fields;

using TravelSite.Entities;

namespace TravelSite.Code
{
    /// <summary>
    /// Summary description for WordInterop.
    /// </summary>
    public class WordInterop
    {
        private static HttpContext contextCurrent
        {
            get
            {
                return System.Web.HttpContext.Current;
            }
        }

        private static readonly License wordLicence;

        static WordInterop()
        {
            //wordLicence = new License();
            //wordLicence.SetLicense(contextCurrent.Server.MapPath("~/Aspose.Word.lic"));
        }

        public static Document StartWordDocument(string dotFileName)
        {
            Document doc = null;
            try
            {
                doc = new Document(dotFileName);
            }
            catch
            {
            }
            return doc;
        }

        public static bool IsLicensed
        {
            get
            {
                return wordLicence is License;
            }
        }

        private static string GetFieldName(string fieldDef)
        {
            string result = "";
            bool flagNext = false;
            string[] arr = fieldDef.Split(new char[] {' '});
            for(int i = 0; i < arr.Length; ++i)
            {
                string str = arr[i];

                if (flagNext && (!string.IsNullOrEmpty(str.Trim())))
                {
                    result = str.Trim();
                    break;
                }

                if (str.Trim().ToUpper() == "FILLIN")
                    flagNext = true;
            }

            return result;
        }

        public static string DocumentFields(string path)
        {
            string result = "";

            try
            {
                //Open document
                Document doc = new Document(path);
                //Create DocuentBuilder. It will help us to modify fields
                DocumentBuilder builder = new DocumentBuilder(doc);

                //Get collection of FieldStart nodes
                NodeCollection starts = doc.GetChildNodes(NodeType.FieldStart, true);

                //loop through all field starts and search for FILLIN fields
                foreach (FieldStart start in starts)
                {
                    if (start.FieldType == FieldType.FieldFillIn)
                    {
                        //Every field in MS Word document consists of FieldStart, FieldSeparator, FieldEnd nodes
                        //And Runs that represent field code and field value (displayed text)
                        //If you need to change value of fillin field, you should change field code
                        //And field value
                        Node fieldSeparator;
                        Node fieldEnd;
                        //We should get field code and field value
                        string fieldCode = string.Empty;
                        string fieldValue = string.Empty;
                        Node currentNode = start.NextSibling;
                        //Get Field code
                        while (currentNode.NodeType != NodeType.FieldSeparator)
                        {
                            if (currentNode.NodeType == NodeType.Run)
                                fieldCode += (currentNode as Run).Text;
                            currentNode = currentNode.NextSibling;
                        }
                        fieldSeparator = currentNode;
                        currentNode = currentNode.NextSibling;
                        //Get field value
                        while (currentNode.NodeType != NodeType.FieldEnd)
                        {
                            if (currentNode.NodeType == NodeType.Run)
                            {
                                fieldValue += (currentNode as Run).Text;

                                // Change value code
                                /*Run newValue = new Run(doc, "SuperAlex");
                                int indexNode = currentNode.ParentNode.ChildNodes.IndexOf(currentNode);
                                currentNode.ParentNode.ChildNodes.Insert(indexNode, newValue);
                                currentNode = currentNode.NextSibling;
                                currentNode.PreviousSibling.Remove();*/

                                currentNode = currentNode.NextSibling;
                            }
                            else
                                currentNode = currentNode.NextSibling;
                        }
                        fieldEnd = currentNode;

                        if (!string.IsNullOrEmpty(result))
                            result += ";";
                        result += GetFieldName(fieldCode);

                    }
                }

                //doc.Save(path);
                return result;
            }
            catch(Exception e)
            {
                return "";
            }
        }

        public static string DocumentPlaceHolders(string path)
        {
            string result = "";

            try
            {
                //Open document
                Document doc = new Document(path);
                string docText = doc.GetText();

                Regex regex = new Regex(Regex.Escape("[") + "(.*?)" + Regex.Escape("]"));
                MatchCollection matches = regex.Matches(docText);

                foreach (Match match in matches)
                {
                    string field = match.Value.Substring(1, match.Value.Length - 2);
                    if ((field != "CardNumber") && (field != "CardDate") && (field != "CardCVV") && (field != "CardCC"))
                    {
                        if (!string.IsNullOrEmpty(result))
                            result += ";";
                        result += field;
                    }
                }
                                
                return result;
            }
            catch (Exception e)
            {
                return "";
            }
        }

        public static Document DocumentFillFields(string path, List<ContractField> fields)
        {
            try
            {
                //Open document
                Document doc = new Document(path);
                //Create DocuentBuilder. It will help us to modify fields
                DocumentBuilder builder = new DocumentBuilder(doc);

                //Get collection of FieldStart nodes
                NodeCollection starts = doc.GetChildNodes(NodeType.FieldStart, true);

                //loop through all field starts and search for FILLIN fields
                foreach (FieldStart start in starts)
                {
                    if (start.FieldType == FieldType.FieldFillIn)
                    {
                        //Every field in MS Word document consists of FieldStart, FieldSeparator, FieldEnd nodes
                        //And Runs that represent field code and field value (displayed text)
                        //If you need to change value of fillin field, you should change field code
                        //And field value
                        Node fieldSeparator;
                        Node fieldEnd;
                        //We should get field code and field value
                        string fieldCode = string.Empty;
                        string fieldValue = string.Empty;
                        Node currentNode = start.NextSibling;
                        //Get Field code
                        while (currentNode.NodeType != NodeType.FieldSeparator)
                        {
                            if (currentNode.NodeType == NodeType.Run)
                                fieldCode += (currentNode as Run).Text;
                            currentNode = currentNode.NextSibling;
                        }
                        fieldSeparator = currentNode;
                        currentNode = currentNode.NextSibling;
                        //Get field value
                        while (currentNode.NodeType != NodeType.FieldEnd)
                        {
                            if (currentNode.NodeType == NodeType.Run)
                            {
                                fieldValue += (currentNode as Run).Text;

                                // Change value code
                                ContractField field = fields.Find(f => f.FieldName == GetFieldName(fieldCode));
                                string contactColumnValue = field == null ? "" : field.ContactColumnValue;

                                Run newValue = new Run(doc, contactColumnValue);
                                int indexNode = currentNode.ParentNode.ChildNodes.IndexOf(currentNode);
                                currentNode.ParentNode.ChildNodes.Insert(indexNode, newValue);
                                currentNode = currentNode.NextSibling;
                                currentNode.PreviousSibling.Remove();
                            }
                            else
                                currentNode = currentNode.NextSibling;
                        }
                        fieldEnd = currentNode;
                    }
                }

                return doc;
                
            }
            catch (Exception e)
            {
                return null;
                
            }
        }

        public static Document DocumentFillPlaceHolders(string path, List<ContractField> fields)
        {
            try
            {
                //Open document
                Document doc = new Document(path);
                foreach (ContractField field in fields)
                {
                    doc.Range.Replace("[" + field.FieldName + "]", field.ContactColumnValue, false, false);
                }
                
                return doc;

            }
            catch (Exception e)
            {
                return null;

            }
        }

        public static MemoryStream DocumentToPdf(Document doc)
        {
            MemoryStream docStream = new MemoryStream();
            doc.Save(docStream, SaveFormat.Pdf);
            return docStream;
        }
    }
}